package com.lz.sports.widget

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.lz.sports.R
import java.io.ByteArrayOutputStream
import java.io.FileOutputStream
import kotlin.math.abs

//签名
class SignatureView : View {
    //画笔x坐标起点
    private var penX = 0f
    //画笔y坐标起点
    private var penY = 0f
    //画笔宽度
    private var penSize = 10f
    //画笔颜色
    private var penColor = Color.BLACK
    //画板颜色
    private var bgColor = Color.WHITE
    //画笔
    private val paint by lazy { Paint()}
    //描点
    private val path by lazy { Path() }
    //画的bitmap
    private var canvas: Canvas? = null
    private var cacheBitmap: Bitmap? = null

    constructor(context: Context) : super(context) {
        init(context, null)
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init(context, attrs)
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        init(context, attrs)
    }

    private fun init(context: Context, attrs: AttributeSet?) {
        if (attrs != null) {
            val typedArray = context.obtainStyledAttributes(attrs, R.styleable.SignatureView)
            penColor = typedArray.getColor(R.styleable.SignatureView_signPenColor, penColor)
            bgColor = typedArray.getColor(R.styleable.SignatureView_signBgColor, bgColor)
            penSize = typedArray.getDimension(R.styleable.SignatureView_signPenSize, penSize)
            typedArray.recycle()
        }
        paint.isAntiAlias = true
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = penSize
        paint.color = penColor
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        if (cacheBitmap != null) {
            val newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
            canvas!!.setBitmap(newBitmap)
            cacheBitmap!!.recycle()
            cacheBitmap = newBitmap
            canvas!!.drawColor(bgColor)
        } else {
            cacheBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
            canvas = Canvas(cacheBitmap!!).apply { drawColor(bgColor) }
        }
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        cacheBitmap?.also { canvas.drawBitmap(it, 0f, 0f, paint) }
        canvas.drawPath(path, paint)
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                penX = event.x
                penY = event.y
                path.moveTo(penX, penY)
                return true
            }
            MotionEvent.ACTION_MOVE -> {
                val x = event.x
                val y = event.y
                val penX = penX
                val penY = penY
                val dx = abs(x - penX)
                val dy = abs(y - penY)
                if (dx >= 3 || dy >= 3) {
                    val cx = (x + penX) / 2
                    val cy = (y + penY) / 2
                    path.quadTo(penX, penY, cx, cy)
                    this.penX = x
                    this.penY = y
                }
                invalidate()
            }
            MotionEvent.ACTION_UP -> {
                canvas?.drawPath(path, paint)
                path.reset()
            }
        }
        return super.onTouchEvent(event)
    }

    fun clear() {
        canvas?.also {
            it.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
            it.drawColor(bgColor)
            invalidate()
        }
    }

    fun save(path: String): Boolean {
        return try {
            ByteArrayOutputStream().use { outs ->
                cacheBitmap!!.compress(Bitmap.CompressFormat.PNG, 100, outs)
                FileOutputStream(path).use { it.write(outs.toByteArray()) }
            }
            true
        } catch (e: Exception) {
            false
        }
    }
}